/*
 * ProtocolParser.cpp
 *
 *  Created on: Sep 7, 2017
 *      Author: guoxs
 */
#include <vector>
#include <string.h>
#include <system/Mutex.h>
#include "CommDef.h"
#include "uart/ProtocolParser.h"
#include "utils/Log.h"
#include "uart/ProtocolSender.h"

static Mutex sLock;
static std::vector<OnProtocolDataUpdateFun> sProtocolDataUpdateListenerList;

void registerProtocolDataUpdateListener(OnProtocolDataUpdateFun pListener) {
	Mutex::Autolock _l(sLock);
	LOGD("registerProtocolDataUpdateListener\n");
	if (pListener != NULL) {
		sProtocolDataUpdateListenerList.push_back(pListener);
	}
}

void unregisterProtocolDataUpdateListener(OnProtocolDataUpdateFun pListener) {
	Mutex::Autolock _l(sLock);
	LOGD("unregisterProtocolDataUpdateListener\n");
	if (pListener != NULL) {
		std::vector<OnProtocolDataUpdateFun>::iterator iter = sProtocolDataUpdateListenerList.begin();
		for (; iter != sProtocolDataUpdateListenerList.end(); iter++) {
			if ((*iter) == pListener) {
				sProtocolDataUpdateListenerList.erase(iter);
				return;
			}
		}
	}
}

static void notifyProtocolDataUpdate(const SProtocolData &data) {
	Mutex::Autolock _l(sLock);
	std::vector<OnProtocolDataUpdateFun>::const_iterator iter = sProtocolDataUpdateListenerList.begin();
	for (; iter != sProtocolDataUpdateListenerList.end(); iter++) {
		(*iter)(data);
	}
}

static SProtocolData sProtocolData;

SProtocolData& getProtocolData() {
	return sProtocolData;
}

/**
 * 获取校验码
 * Get checksum code
 */
BYTE getCheckSum(const BYTE *pData, int len) {
	int sum = 0;
	for (int i = 0; i < len; ++i) {
		sum += pData[i];
	}

	return (BYTE) (~sum + 1);
}

/**
 * 解析每一帧数据
 * Parse each frame of data
 */
extern bool Charge_sleep_flag;
static void procParse(const BYTE *pData, UINT len) {

if(pData[2]!=0xCA&&pData[3]!=0xCA&&pData[4]!=0xCA&&pData[5]!=0xCA)
{
	sProtocolData.BAI = pData[2]&0x0F;
	sProtocolData.SHI = (pData[3]>>4)&0x0F;
	sProtocolData.GE = pData[3]&0x0F;
	sProtocolData.D_SHI = (pData[4]>>4)&0x0F;
	sProtocolData.D_GE = pData[4]&0x0F;

	if(pData[2]==0xD5&&pData[3]==0xD5&&pData[4]==0xD5)
	{
		Charge_sleep_flag = true;
		sProtocolData.BatCharge = 1;
	}
	else if(pData[2]==0x20)
	{

		Charge_sleep_flag = false;


		sProtocolData.KGorLB = pData[5]&0x05;
		if((pData[5]&0xC0)==0xC0)
			sProtocolData.BatCharge = 2;//充满电
		else if((pData[5]&0xC0)==0x40)
			sProtocolData.BatCharge = 1;
		else if((pData[5]&0xC0)==0x00)
			sProtocolData.BatCharge = 0;

		if((pData[6]&0x3f)==0x3f)
			sProtocolData.BAT_level = 5;
		else if((pData[6]&0x3f)==0x1f)
			sProtocolData.BAT_level = 4;
		else if((pData[6]&0x3f)==0x0f)
			sProtocolData.BAT_level = 3;
		else if((pData[6]&0x3f)==0x07)
			sProtocolData.BAT_level = 2;
		else if((pData[6]&0x3f)==0x03)
			sProtocolData.BAT_level = 1;
		else if((pData[6]&0x3f)==0x01)
			sProtocolData.BAT_level = 0;
		//LOGD(" 99999999999999999sProtocolData.BAT_level---- %x \n", sProtocolData.BAT_level);


	}
	//else
	{
		/////////////////////标定处理///////////////////////
			if(pData[6]&0x40)
				sProtocolData.BiaoDing = 1;
			else
				sProtocolData.BiaoDing = 0;

			if(pData[2]==0xCB&&pData[3]==0xCB&&pData[4]==0xCB&&pData[5]==0xCB)
				sProtocolData.BiaoDing = 2;
			else if(pData[2]==0xCC&&pData[3]==0xCC&&pData[4]==0xCC&&pData[5]==0xCC)
				sProtocolData.BiaoDing = 3;
			else if(pData[2]==0xCD&&pData[3]==0xCD&&pData[4]==0xCD&&pData[5]==0xCD)
				sProtocolData.BiaoDing = 4;
			else if(pData[2]==0xCE&&pData[3]==0xCE&&pData[4]==0xCE&&pData[5]==0xCE)
				sProtocolData.BiaoDing = 5;
		/////////////////////标定处理///////////////////////

			if(pData[2]==0xDA&&pData[3]==0xDA&&pData[4]==0xDA&&pData[5]==0xDA)//进入存储
			{
				sProtocolData.SaveState = 1;
				sendProtocol(0xDA,0,1);
			}
			else if((pData[2]==0xD7&&pData[3]==0xD7&&pData[4]==0xD7&&pData[5]==0xD7))//退出存储
			{
				sProtocolData.SaveState = 0;
				sendProtocol(0xD7,0,1);
			}
			else if((pData[2]==0xD8&&pData[3]==0xD8&&pData[4]==0xD8&&pData[5]==0xD8))//下翻存储
				sProtocolData.SaveState = 2;
			else if((pData[2]==0xD9&&pData[3]==0xD9&&pData[4]==0xD9&&pData[5]==0xD9))//上翻存储
				sProtocolData.SaveState = 3;

			if(pData[2]==0xDB&&pData[3]==0xDB&&pData[4]==0xDB&&pData[5]==0xDB)
				sProtocolData.SaveDeal = 1;
			else
			{
				sProtocolData.SaveDeal = 0;
				sProtocolData.Hold = pData[5]&0x20;
			}

			if(pData[2]==0xD6&&pData[3]==0xD6&&pData[4]==0xD6&&pData[5]==0xD6)
				sProtocolData.QuPi = 1;
			else
				sProtocolData.QuPi = 0;
	}
}
	// 通知协议数据更新
  // Notify protocol data update
	notifyProtocolDataUpdate(sProtocolData);
}

/**
 * 功能：解析协议 
 * Function: Parse protocol
 * 参数：pData 协议数据，len 数据长度
 * Parameters: pData - protocol data, len - data length
 * 返回值：实际解析协议的长度
 * Return value: the length of the actual resolution protocol
 */
int parseProtocol(const BYTE *pData, UINT len) {
	UINT remainLen = len;	// 剩余数据长度 Remaining data length
	UINT dataLen;	// 数据包长度 Packet length
 	UINT frameLen;	// 帧长度 Frame length
 	UINT i;

#ifdef DEBUG_PRO_DATA
 		LOGD("\n");
		for (i = 0; i < len; ++i) {
			LOGD("%2x ", pData[i]);
		}
		if(i==8)
			LOGD("\n");
#endif
		procParse(pData, len);
	/**
	 * 以下部分需要根据协议格式进行相应的修改，解析出每一帧的数据
   * The following parts need to be modified according to the protocol format to parse out the data of each frame
	 */
	while (remainLen >= DATA_PACKAGE_MIN_LEN) {
		// 找到一帧数据的数据头
    // Find the data header of a frame of data
		while ((remainLen >= 2) && ((pData[0] != CMD_HEAD1) || (pData[1] != CMD_HEAD2))) {
			pData++;
			remainLen--;
			continue;
		}

		if (remainLen < DATA_PACKAGE_MIN_LEN) {
			break;
		}

		dataLen = pData[4];
		frameLen = dataLen + DATA_PACKAGE_MIN_LEN;
		if (frameLen > remainLen) {
			// 数据内容不全
      // Incomplete data packet
			break;
		}

		// 打印一帧数据，需要时在CommDef.h文件中打开DEBUG_PRO_DATA宏
    // To print a data of frame, open the DEBUG_PRO_DATA macro in the CommDef.h file when needed
#ifdef DEBUG_PRO_DATA
		for (UINT i = 0; i < frameLen; ++i) {
			LOGD("%x ", pData[i]);
		}
		LOGD("\n");
#endif

		// 支持checksum校验，需要时在CommDef.h文件中打开PRO_SUPPORT_CHECK_SUM宏
    // Support checksum verification, open the PRO_SUPPORT_CHECK_SUM macro in CommDef.h file when needed
#ifdef PRO_SUPPORT_CHECK_SUM
		// 检测校验码 Checksum
		if (getCheckSum(pData, frameLen - 1) == pData[frameLen - 1]) {
			// 解析一帧数据
      // Parse a data of frame
			procParse(pData, frameLen);
		} else {
			LOGE("CheckSum error!!!!!!\n");
		}
#else
		// 解析一帧数据
    // Parse a data of frame
		procParse(pData, frameLen);
#endif

		pData += frameLen;
		remainLen -= frameLen;
	}

	return len - remainLen;
}
